#ifndef __CFGPARSER_H__
#define __CFGPARSER_H__

#include <string>
#include <type_traits>
#include <cstring>
#include <memory>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <chrono>
#include <atomic>
#include <utility>

#include "cfgparser_prefs.h"
#include "cfgparser_storage_path.h"

namespace cfgparser
{
    struct CFGParserOptions
    {
        /// @brief 构造时尝试加载已有配置文件
        bool auto_load_on_construction{false};

        /// @brief 析构时如果存在未持久化数据则自动保存
        bool auto_save_on_destruction{false};

        /// @brief 在调用 set 后启用去抖自动保存（会启动后台线程）
        bool auto_save_on_change{false};

        /// @brief 去抖延迟（毫秒），当启用 auto_save_on_change 时生效
        int auto_save_debounce_ms{2000};

        /// @brief 如果配置文件不存在则创建
        bool create_if_not_exists{true};

        /// @brief 加载配置文件前备份已有文件
        bool backup_on_load{false};

        /// @brief 备份文件的后缀
        std::string backup_suffix{".bak"};
    };

    class CFGParser : public cfgparser::Preferences
    {
    public:
        CFGParser();

        /// @brief 构造函数
        /// @param config_file_path 配置文件路径
        explicit CFGParser(const std::string &config_file_path);

        /// @brief 构造函数
        /// @param config_file_path 配置文件路径
        /// @param options 解析器行为配置
        CFGParser(const std::string &config_file_path, CFGParserOptions options);

        virtual ~CFGParser();

        /// @brief 获取配置文件路径
        /// @return 配置文件路径
        const std::string &get_config_file_path() const;

        /// @brief 设置配置文件路径
        /// @return 是否加载成功
        bool load();

        /// @brief 设置配置文件路径并加载
        /// @param config_file_path 配置文件路径
        /// @return 是否加载成功
        /// @note 如果传入空字符串则保持当前路径不变并尝试加载
        bool reload(const std::string &config_file_path = "");

        /// @brief 保存配置文件
        /// @param config_file_path 配置文件路径
        /// @return 是否保存成功
        /// @note 该函数调用 save_as 并传入当前配置文件路径，但并不会修改当前配置文件路径
        bool save_as(const std::string &config_file_path);

        /// @brief 保存配置文件到当前路径
        /// @return 是否保存成功
        bool save();

        /// @brief 更新解析器配置
        CFGParser &set_options(const CFGParserOptions &options);

        /// @brief 获取当前解析器配置
        CFGParserOptions get_options() const;

        /// @brief 设置键值对，支持链式调用
        /// @tparam ARGS_T 可变参数模板
        /// @param args 传递给 Preferences::set 的参数
        /// @return 当前对象引用，便于链式调用
        template <typename... ARGS_T>
        CFGParser &set(ARGS_T &&...args)
        {
            (void)Preferences::set(std::forward<ARGS_T>(args)...);
            // 通知自动保存去抖
            __notify_autosave();
            return *this;
        }

        /// @brief 设置键值对，如果不相等则更新，支持链式调用
        /// @tparam ARGS_T 可变参数模板
        /// @param args 传递给 Preferences::set 的参数
        /// @return 当前对象引用，便于链式调用
        template <typename... ARGS_T>
        CFGParser &set_if_not_equal(ARGS_T &&...args)
        {
            (void)Preferences::set_if_not_equal(std::forward<ARGS_T>(args)...);
            // 通知自动保存去抖
            __notify_autosave();
            return *this;
        }

        /// @brief 设置键值对，如果不存在则创建，支持链式调用
        /// @tparam ARGS_T 可变参数模板
        /// @param args 传递给 Preferences::set_if_no_key 的参数
        /// @return 当前对象引用，便于链式调用
        template <typename... ARGS_T>
        CFGParser &set_if_no_key(ARGS_T &&...args)
        {
            (void)Preferences::set_if_no_key(std::forward<ARGS_T>(args)...);
            // 通知自动保存去抖
            __notify_autosave();
            return *this;
        }

    private:
        std::string __config_file_path;
        mutable std::mutex __io_mutex;
        CFGParserOptions __options{};

        bool ensure_config_file_exists();
        bool backup_config_file();
        // 自动保存去抖相关成员
        mutable std::mutex __autosave_mtx;                // 保护下面成员的互斥量
        std::condition_variable __autosave_cv;            // 用于通知后台线程
        std::thread __autosave_thread;                    // 后台 autosave 线程
        std::atomic<bool> __autosave_running{false};      // 线程是否运行中
        std::atomic<bool> __autosave_stop{false};         // 请求线程停止的标志
        bool __autosave_pending{false};                   // 是否存在待处理的保存请求
        std::chrono::milliseconds __autosave_delay{2000}; // 去抖延迟（可由 options 覆盖）

        // 触发去抖自动保存（在 set 操作后调用）
        void __notify_autosave();
        // 后台线程循环实现
        void __autosave_thread_loop();
    };

    /// @brief 默认配置解析器
    inline static CFGParser default_parser{
        ::cfgparser::get_default_config_path(::cfgparser::get_app_name()) + "/config.bin"};

}

#endif // __CFGPARSER_H__